package com.zpp.gobang.game;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.zpp.gobang.GobangApplication;
import com.zpp.gobang.model.User;
import com.zpp.gobang.service.UserService;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.UUID;

/**游戏房间对象
 * 需要一个房间号
 *    两个游戏玩家
 */
@Data
public class Room {
    private String roomId;

    private User user1;
    private User user2;

    private int whiteUser;

    private static final int MAX_ROW = 15;
    private static final int MAX_COL = 15;
    public Room() {
        this.roomId = UUID.randomUUID().toString();

        //通过入口类中记录的 context手动获取
        onlineUserManager = GobangApplication.context.getBean(OnlineUserManager.class);
        roomManager = GobangApplication.context.getBean(RoomManager.class);
        userService = GobangApplication.context.getBean(UserService.class);
    }

    //@Autowired
    //Room没有添加进spring容器中，不能自动注入只能手动注入
    private OnlineUserManager onlineUserManager;

    //@Autowired
    private RoomManager roomManager;

    private UserService userService;

    private ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 二维数组表示棋盘
     *0 表示未落子区域
     *1 表示user1的落子位置
     *2 表示user2的落子位置
     */
    private int[][] board = new int[MAX_ROW][MAX_COL];

    public void putChess(GameRequest request) throws IOException {
        //1.记录当前落子的位置
        //判断是哪个用户的下的棋
        int chess = request.getUserId() == user1.getUserId() ? 1 : 2;
        int row = request.getRow();
        int col = request.getCol();
        if(board[row][col] != 0){
            System.out.println("当前位置("+row + ","+col + ")已经有子了");
            return;
        }
        board[row][col] = chess;
        //2.打印出棋盘信息，方便观察局势
        printBoard();
        //3.进行胜负判定
        int winner = checkWinner(row,col,chess);
        //4.给客户端响应
        //给房间中的所有客户端返回响应
        GameResponse response = new GameResponse();
        response.setMessage("putChess");
        response.setUserId(request.getUserId());
        response.setRow(row);
        response.setCol(col);
        response.setWinner(winner);

        WebSocketSession session1 = onlineUserManager.getFromGameRoom(user1.getUserId());
        WebSocketSession session2 = onlineUserManager.getFromGameRoom(user2.getUserId());
        //判定session是否为空，玩家是否下线了
        if (session1 == null) {
            //玩家1下线了，直接让玩家2获胜
            response.setWinner(user2.getUserId());
            System.out.println("玩家1掉线");
        }
        if (session2 == null) {
            //玩家2下线了，直接让玩家1获胜
            response.setWinner(user1.getUserId());
            System.out.println("玩家2掉线");
        }

        String json = objectMapper.writeValueAsString(response);
        if(session1 != null) {
            session1.sendMessage(new TextMessage(json));
        }
        if(session2 != null) {
            session2.sendMessage(new TextMessage(json));
        }

        //如果胜负已分，则可以销毁房间
        if(response.getWinner() != 0 ) {
            System.out.println("游戏结束！roomId = "+ roomId + "获胜方为" + response.getUserId());
            //更新胜方和败方分数
            int winUserId = response.getWinner();
            int loseUserId = winUserId == user1.getUserId() ? user2.getUserId() : user1.getUserId();
            userService.winUSer(winUserId);
            userService.loseUser(loseUserId);

            //销毁房间
            roomManager.remove(roomId,user1.getUserId(),user2.getUserId());
        }
    }

    //打印出棋盘
    private void printBoard() {
        System.out.println("[打印棋盘信息]  房间号：" + roomId);
        System.out.println("============================================");
        for(int r = 0; r < MAX_ROW; r++){
            for(int c = 0; c < MAX_COL; c++){
                System.out.print(board[r][c] + "  ");
            }
            System.out.println();
        }
        System.out.println("============================================");
    }

    /**
     *如果玩家1获胜返回1
     *如果玩家2获胜返回2
     * 胜负未分则返回0
     */
    private int checkWinner(int row, int col, int chess) {

        //1.检查所有行
        for(int c = col -4; c <= col; c++){
            try {
                  if(board[row][c] == chess
                     && board[row][c+1] == chess
                     && board[row][c+2] == chess
                     && board[row][c+3] == chess
                     && board[row][c+4] == chess ){
                   //构成五子连珠，返回赢方id
                   return chess == 1 ? user1.getUserId() : user2.getUserId();
                   }
            }catch (ArrayIndexOutOfBoundsException e) {
                //数组越界直接跳过
                continue;
            }
        }

        //2.检查所有列
        for(int r = row -4; r <= row; r++){
            try {
                if(board[r][col] == chess
                        && board[r+1][col] == chess
                        && board[r+2][col] == chess
                        && board[r+3][col] == chess
                        && board[r+4][col] == chess ){
                    //构成五子连珠，返回赢方id
                    return chess == 1 ? user1.getUserId() : user2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e) {
                //数组越界直接跳过
                continue;
            }
        }

        //3.检查对角线
        //左对角线
        for(int r = row -4, c = col - 4; r <= row && c <= col; r++,c++){
            try {
                if(board[r][c] == chess
                        && board[r+1][c+1] == chess
                        && board[r+2][c+2] == chess
                        && board[r+3][c+3] == chess
                        && board[r+4][c+4] == chess ){
                    //构成五子连珠，返回赢方id
                    return chess == 1 ? user1.getUserId() : user2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e) {
                //数组越界直接跳过
                continue;
            }
        }
        //右对角线
        for(int r = row -4, c = col + 4; r <= row && c >= col; r++,c--){
            try {
                if(board[r][c] == chess
                        && board[r+1][c-1] == chess
                        && board[r+2][c-2] == chess
                        && board[r+3][c-3] == chess
                        && board[r+4][c-4] == chess ){
                    //构成五子连珠，返回赢方id
                    return chess == 1 ? user1.getUserId() : user2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e) {
                //数组越界直接跳过
                continue;
            }
        }

        //胜负未分
        return 0;
    }
}
